<template>
    <view id="box" ref="box" :style="{ width: props.width + 'rpx', height: props.height + 'rpx' }">
        <!-- <view 
        class="flex flex-row-top-start flex-row flex-wrap"
        :style="{ width: props.width + 'rpx', height: props.height + 'rpx', background: 'red' }">
            <view v-for="(item, index) in _data" :key="index"
                :style="{ width: `${item.width}px`, height: `${item.height}px`, background: 'yellow' }">
                {{ item._id }}
            </view>
        </view> -->
        <movable-area :style="{ width: props.width + 'rpx', height: props.height + 'rpx' }">
            <movable-view :class="[moveIndex === item._index ? 'opacity-6 zIndex-1' : 'zIndex-0']" :animation="false"
                @touchstart="drageStart" @touchmove="onTouchMove($event, index)" @touchcancel="dragEnd($event, index)"
                @touchend="dragEnd($event, index)" @change="eleChange($event, index)" :x="item._x" :y="item._y" :style="{
                    width: `${item.width}px`,
                    height: `${item.height}px`,
                    background: 'white',
                }" class="" :data-index="item._index" direction="all" v-for="(item, index) in _data" :key="index">
                <view :class="[onmoveIndex === index ? 'onSelecteItemStyle ' : '', 'onSelecteItem ']">
                    <tm-sheet :border="0" :margin="[0]" :padding="[0]" :width="item.width" :height="item.height"
                        unit="px" :color="onmoveIndex === index ? 'grey-2' : props.color"
                        _class="flex flex-col flex-col-center-center">
                        <tm-icon v-if="item.icon" :font-size="props.iconSize" :name="item?.icon ?? ''"></tm-icon>
                        <tm-text _class="text-align-center" :font-size="props.fontSize"
                            :label="item?.text ?? ''"></tm-text>
                    </tm-sheet>
                </view>
            </movable-view>
        </movable-area>
    </view>
</template>
<script setup lang="ts">
/**
 * 宫格排序，
 * 在nvue上：
 * 截止3.6.18 uni sdk 的movable有bug,具体来说是动态修改宽和高时，可移动范围会跑上面去。
 * 理论上是支持nvue，只有当uni修复此bug才可使用，否则，请使用vue页面。
 *
 */
import customProps from "./customProps";
import type { cellOptsType } from "./interface";
import tmSheet from "../tm-sheet/tm-sheet.vue";
import tmText from "../tm-text/tm-text.vue";
import tmIcon from "../tm-icon/tm-icon.vue";
import { ref, Ref, nextTick, onMounted, watch, getCurrentInstance } from "vue";
const props = defineProps(customProps);
const emits = defineEmits(["start", "end"]);
const boxHeight = ref(0);
const proxy = getCurrentInstance()?.proxy ?? null;
let cellWidth = 0;
let cellHeight = 0;
let maxRow = 0;
const _data: Ref<Array<cellOptsType>> = ref([]);
const movexy = { x: 0, y: 0 };
//当前拖动的项目
const moveIndex = ref(-1);
//即将替换的项目
const onmoveIndex = ref(-1);
let tid: any = NaN;
let boxOpts = { left: 0, top: 0 };
const onMoveStauts = ref(false);
let testdata: Array<any> = props.list;
onMounted(() => {
    watchOpts();
    setTimeout(() => {
        uni.$tm.u.quereyDom(proxy, "#box").then((ev: any) => {
            if (ev) {
                boxOpts.left = ev.left;
                boxOpts.top = ev.top;
            }
        });
    }, 50);
});
watch(
    () => props.list,
    () => {
        testdata = uni.$tm.u.deepClone(props.list);
        watchOpts();
    },
    { deep: true }
);
function watchOpts() {
    clearTimeout(tid);
    tid = setTimeout(() => {
        initOpts();
    }, 100);
}
function initOpts(isOld: boolean = false) {
    let col = props.column;
    if (!isOld) {
        testdata = testdata.map((el, index) => {
            el["_id"] = index;
            return el;
        });
    }
    let data = uni.$tm.u.deepClone(testdata);

    let d: Array<Array<cellOptsType>> = uni.$tm.u.splitData(data, col);
    let row = d.length;
    maxRow = row;
    // uni sdk3.6.18有bug，如果自动计算高度会导致拖动区域异常。
    // boxHeight.value = uni.upx2px(row * props.itemHeight)
    cellWidth = uni.upx2px(props.width / col);
    cellHeight = uni.upx2px(props.itemHeight);
    d = d.map((el, index) => {
        el = el.map((ele, index2) => {
            ele._index = index * col + index2;
            ele._id = ele["_id"];
            if (!isOld) {
                ele._x = index2 * cellWidth;
                ele._y = index * cellHeight;
            } else {
                ele._x = index2 * cellWidth - 0.5;
                ele._y = index * cellHeight - 0.5;
            }
            ele._newx = index2 * cellWidth;
            ele._newy = index * cellHeight;
            ele.width = cellWidth;
            ele.height = cellHeight;
            return ele;
        });
        return el;
    });

    _data.value = [];
    let dtestdata: any = [];
    d.forEach((el) => {
        dtestdata.push(...el);
    });
    _data.value = [...dtestdata];
    if (isOld) {
        setTimeout(() => {
            _data.value = _data.value.map((ele) => {
                ele._x = ele._newx;
                ele._y = ele._newy;
                return ele;
            });
        }, 50);
    }
}

function eleChange(ev: any, index: number) {
    if (!onMoveStauts.value) return;
    let { x, y } = ev.detail;
    movexy.x = x;
    movexy.y = y;
    moveIndex.value = index;
}
function onTouchMove(ev: any, index: number) {
    if (!onMoveStauts.value) return;
    clearTimeout(tid);
    tid = setTimeout(() => {
        onmoveIndex.value = getNowXyindex(ev, index);
        // #ifndef H5
        try {
            uni.vibrateShort({});
        } catch (error) { }
        // #endif
        if (!onMoveStauts.value) {
            onmoveIndex.value = -1;
        }
    }, 150);
}
function drageStart() {
    onMoveStauts.value = true;
    emits("start", testdata);
}
function dragEnd(ev: any, index: number) {
    onMoveStauts.value = false;
    let olddata = uni.$tm.u.deepClone(testdata);
    let data = uni.$tm.u.deepClone(testdata);
    const item = data[index];
    let newinex = getNowXyindex(ev, index);
    const [removed] = data.splice(newinex, 1, item);
    data.splice(index, 1, removed);
    testdata = [...data];
    initOpts(true);
    moveIndex.value = -1;
    onmoveIndex.value = -1;
    emits("end", testdata, olddata);
}
function getNowXyindex(ev: any, nowIndex: number = 0) {
    let { clientX, clientY, pageX, pageY } = ev.changedTouches[0];
    let cx = clientX ?? pageX;
    let cy = clientY ?? pageY;
    let newinex = 0;
    cx = cx <= boxOpts.left ? boxOpts.left : cx;
    cy = cy <= boxOpts.top ? boxOpts.top : cy;
    let x = cx - boxOpts.left;
    let y = cy - boxOpts.top;
    let nx = Math.floor(x / cellWidth);
    let ny = Math.floor(y / cellHeight);
    if (ny >= maxRow - 1) {
        ny = maxRow - 1;
    }
    if (nx >= props.column - 1) {
        nx = props.column - 1;
    }
    newinex = ny * props.column + nx;
    if (newinex >= testdata.length) {
        newinex = testdata.length - 1;
    }
    return newinex;
}
</script>
<style scoped>
.onSelecteItem {
    transition-property: transform;
    transition-duration: 0.3s;
    transition-timing-function: ease;
}

.onSelecteItemStyle {
    transform: scale(0.9);
}
</style>
